///<reference path='../SharedWorker.d.ts' />

import { OnDestroy } from "@angular/core";

export class EliteWorker implements OnDestroy {

    private _worker: Worker;
    private _sharedWorker: SharedWorker.SharedWorker;
    private _isClosed: boolean;

    constructor(workerUrl: string, isSharedWorker?: boolean) {
        this.createWorker(workerUrl, isSharedWorker);
    }

    createWorker(workerUrl: string, isSharedWorker?: boolean) {
        if (isSharedWorker) {
            this._sharedWorker = new SharedWorker(workerUrl);
        } else {
            this._worker = new Worker(workerUrl);
        }
    }

    onmessage(messageHander: (this: MessagePort | Worker, _ev: MessageEvent) => any) {
        if (this._sharedWorker) {
            this._sharedWorker.port.onmessage = messageHander;
        } else {
            this._worker.onmessage = messageHander;
        }
    }

    close(): void {
        if (this._sharedWorker) {
            this._sharedWorker.port.close();
        } else {
            this._worker.terminate();
        }

        this._isClosed = true;
    }

    postMessage(message?: any, transfer?: any[]): void {
        if (this._sharedWorker) {
            this._sharedWorker.port.postMessage(message, transfer);
        } else {
            this._worker.postMessage(message, transfer);
        }
    }

    start(): void {
        if (this._sharedWorker) {
            this._sharedWorker.port.start();
        }
    }

    onerror(errorHandler: (ev: ErrorEvent) => any) {
        if (this._sharedWorker) {
            this._sharedWorker.onerror = errorHandler;
        } else {
            this._worker.onerror = errorHandler;
        }
    }

    ngOnDestroy(): void {
        if (!this._isClosed) {
            this.close();
        }

        if (this._sharedWorker) {
            this._sharedWorker.port.onmessage = null;
            this._sharedWorker.port = null;
            this._sharedWorker.onerror = null;
            this._sharedWorker = null;
        }

        if (this._worker) {
            this._worker.onerror = null;
            this._worker.onmessage = null;
            this._worker = null;
        }
    }
}